#ifndef _PACKDEF_H__
#define _PACKDEF_H__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma pack(push, 1)
/* Ethernet header */
typedef struct ether_header
{
	u_char dhost[6];      // Destination eth addr 
	u_char shost[6];      // Source ether addr    
	u_short type;         // Packet type ID field 
}ether_header;

/* 4 bytes IP address */
typedef struct ip_address{
    u_char byte1;
    u_char byte2;
    u_char byte3;
    u_char byte4;
}ip_address;

/* ARP frame header */
typedef struct arp_header
{
	u_short hw;				// Hardware type
	u_short proto;			// Protocol type
	u_char hw_len;			// Length of hardware address
	u_char proto_len;		// Length of protocol address
	u_short code;			// 1 - Request & 2 - Answer
	u_char snd_hw[6];		// Sender hardware address
	ip_address snd_proto;		// Sender protocol address
	u_char targ_hw[6];		// Target hardware address
	ip_address targ_proto;		// Target protocol address
	u_char padding[18];		// 
}arp_header;

/* IPv4 header */
typedef struct ip_header{
    u_char  ver_ihl;        // Version (4 bits) + Internet header length (4 bits)
    u_char  tos;            // Type of service 
    u_short tlen;           // Total length 
    u_short id;				// Identification
    u_short flags_fo;       // Flags (3 bits) + Fragment offset (13 bits)
    u_char  ttl;            // Time to live
    u_char  proto;          // Protocol
    u_short crc;            // Header checksum
    ip_address  saddr;      // Source address
    ip_address  daddr;      // Destination address
    u_int   op_pad;         // Option + Padding
}ip_header;

/* UDP header*/
typedef struct udp_header{
    u_short sport;          // Source port
    u_short dport;          // Destination port
    u_short len;            // Datagram length
    u_short crc;            // Checksum
}udp_header;


/* TCP header*/
typedef struct tcp_header{
    u_short sport;          // Source port
    u_short dport;          // Destination port
	u_long seq;				// Sequence number
	u_long ack;				// ACK number
	u_char hlen;			// Header length
	u_char flags;			// Option flags
	u_short wnd;			// Window pointer
	u_short crc;            // Checksum
    u_short urgent;         // Urgent pointer
}tcp_header;

/* ICMP header */
typedef struct icmp_header
{
	u_char type;			// Message type
	u_char code;			// Code
	u_short crc;			// Checksum
	union
	{
		struct
		{
			u_short id;				// Identification
			u_short seq;			// Sequence number
		}echo;
		u_long gateway;				// Gateway address
		struct 
		{
			u_short __unused;
			u_short mtu;			// Path mtu discovery
		}frag;
	};
	u_long ts;				// Timestamp
}icmp_header;

/* IGMP header */
typedef struct igmp_header
{
	u_char ver_type;		// Version & type
	u_char resv;			// Reserved
	u_short crc;			// Checksum
	u_long gp_addr;			// 32bit Group address
}igmp_header;

#define TCP_FLAG_FIN	(0x01)
#define TCP_FLAG_SYN	(0x02)
#define TCP_FLAG_RST	(0x04)
#define TCP_FLAG_PUSH	(0x08)
#define TCP_FLAG_ACK	(0x10)
#define TCP_FLAG_URGE	(0x20)

/* DNS header */
typedef struct dns_header
{
	u_short id;				// Identification
	u_short flags;			// Flags
	u_short quest_no;		// Questions
	u_short ans;			// Answer RRS
	u_short auth;			// Authority RRS
	u_short addition;		// Additional RRS
	u_char buf[1];
}dns_header;

#define DNS_FLAG_RESONSE	(0x8000)
#define DNS_FLAG_OPCODE		(0x7800)
#define DNS_FLAG_AUTHORITY	(0x0400)
#define DNS_FLAG_TRUNCATED	(0x0200)
#define DNS_FLAG_RECDESIRE	(0x0100)
#define DNS_FLAG_RECAVAIL	(0x0080)
#define DNS_FLAG_RESERVED	(0x0070)
#define DNS_FLAG_RETCODE	(0x000F)

/* OICQ header */
typedef struct oicq_header
{
	u_char flag;		// Sync flag
	u_short ver;		// Version
	u_short cmd;		// Command
	u_short seq;		// Sequence
	u_long num;			// OICQ number
	u_char buf[1];
}oicq_header;

#define OICQ_FLAG_GETFRIENDSTAT			(129)	// Get status of friend
#define OICQ_FLAG_GROUPOPS				(48)	// Group operation
#define OICQ_FLAG_REQUESTKEY			(29)	// Request key
#define OICQ_FLAG_HEARTBEAT				(2)		// Heart message
#define OICQ_FLAG_LOGOUT				(1)		// Log out
#define OICQ_FLAG_GETFRIENDONLINE		(39)	// Get friend online
#define OICQ_FLAG_GETLEVEL				(92)	// Get level
#define OICQ_FLAG_GROUPNAMEOPS			(60)	// Group name operation
#define OICQ_FLAG_REQUESTEXTRAINFO		(101)	// Request extra information
#define OICQ_FLAG_MEMOOPS				(62)	// MEMO operation
#define OICQ_FLAG_RECVMESSAGE			(23)	// Receive message
#define OICQ_FLAG_REQUESTLOGIN			(98)	// Request login
#define OICQ_FLAG_DLGROUPFRIEND			(88)	// Download group friend
#define OICQ_FLAG_GETGROUPSTAT			(181)	// Get friend's status of group

#pragma pack(pop)

typedef struct
{
	// link_layer
	ether_header* eth;
	// net_layer
	ip_header* ip;
	int proto;
	// trans_layer
	union
	{
		udp_header* udp;
		tcp_header* tcp;
		icmp_header* icmp;
		igmp_header* igmp;
		arp_header* arp;
	};
	// app_layer
	union
	{
		dns_header* dns;
		oicq_header* oicq;
	};
}pack_hdr;

#endif